//@author A0101119Y
#include "FileWriter.h"

using namespace Twentyfifth;
using namespace std;

FileWriter::FileWriter() {
	openFile(FILE_DATABANK);
}

FileWriter::FileWriter(string customFile) {
	openFile(customFile);
}

FileWriter::~FileWriter() {
	closeFile();
}

void FileWriter::openFile(string fileName) {
	if (file.is_open()) {
		file.close();
	}
	file.open(fileName, fstream::out | fstream::trunc);
	return;
}

//
// task writers
//

Status FileWriter::writeTasksToFile(vector<Task> tasks) {
	for (unsigned int i = 0; i < tasks.size(); i++, terminateTaskInFile()) {
		writeTaskToFile(tasks[i]);
	}
	return Status(Status::OK);
}

void FileWriter::writeTaskToFile(Task task) {
	writeLineToFile(LABEL_ID, task.getId());
	writeLineToFile(LABEL_IS_DELETED, task.getDeleted());
	writeLineToFile(LABEL_LAST_UPDATED, task.getLastUpdated());
	writeLineToFile(LABEL_DESCRIPTION, task.getDescription());

	Task::TaskType type = task.getTaskType();
	writeLineToFile(LABEL_TYPE, type);

	switch (type) {
	case Task::TaskType::TIMED_TASK:
		writeLineToFile(LABEL_START, task.getStart());
		writeLineToFile(LABEL_END, task.getEnd());
		writeLineToFile(LABEL_FULL_DAY, task.isFullDay());
		break;
	case Task::TaskType::DEADLINE_TASK:
		writeLineToFile(LABEL_DEADLINE, task.getDeadline());
	case Task::TaskType::TASK:
	default:
		writeLineToFile(LABEL_IS_DONE, task.isDone());
		break;
	}

	string venue = task.getVenue();
	if (venue != BLANK_STRING) {
		writeLineToFile(LABEL_VENUE, venue);
	}

	string gcal_id = task.getGCalId();
	if (gcal_id != BLANK_STRING) {
		writeLineToFile(LABEL_GCAL_ID, gcal_id);
	}


	return;
}

void FileWriter::terminateTaskInFile() {
	writeLineToFile(BLANK_STRING);
	return;
}

//
// line writers
//

void FileWriter::writeLineToFile(string label, string value) {
	file << label;
	file << LABEL_SEPARATOR;
	file << value;
	file << endl;
	return;
}

void FileWriter::writeLineToFile(string label, DateTime value) {
	string datetime = parseDateTimeToString(value);
	writeLineToFile(label, datetime);
	return;
}

void FileWriter::writeLineToFile(string label, int value) {
	string s = to_string(value);
	writeLineToFile(label, s);
	return;
}

void FileWriter::writeLineToFile(string label, bool value) {
	string boolean;
	if (value) {
		boolean = VALUE_BOOL_TRUE;
	} else {
		boolean = VALUE_BOOL_FALSE;
	}
	writeLineToFile(label, boolean);
	return;
}

void FileWriter::writeLineToFile(string label, Task::TaskType value) {
	string tasktype = parseTaskTypeToString(value);
	writeLineToFile(label, tasktype);
}

void FileWriter::writeLineToFile(string line) {
	file << line;
	file << endl;
	return;
}

//
// non-string variable parsers
//

string FileWriter::parseDateTimeToString(DateTime dt) {
	string parsed = VALUE_TIMESTAMP;
	size_t posDay = parsed.find(VALUE_TIMESTAMP_DAY);
	parsed.replace(posDay, 1, padNumberWithZero(dt.getDay()));

	size_t posMonth = parsed.find(VALUE_TIMESTAMP_MONTH);
	parsed.replace(posMonth, 1, padNumberWithZero(dt.getMonth()));

	size_t posYear = parsed.find(VALUE_TIMESTAMP_YEAR);
	parsed.replace(posYear, 1, to_string(dt.getYear()));

	size_t posHour = parsed.find(VALUE_TIMESTAMP_HOUR);
	parsed.replace(posHour, 1, padNumberWithZero(dt.getHour()));

	size_t posMinute = parsed.find(VALUE_TIMESTAMP_MINUTE);
	parsed.replace(posMinute, 1, padNumberWithZero(dt.getMinute()));

	size_t posSecond = parsed.find(VALUE_TIMESTAMP_SECOND);
	parsed.replace(posSecond, 1, padNumberWithZero(dt.getSecond()));
	return parsed;
}

string FileWriter::parseTaskTypeToString(Task::TaskType tt) {
	switch (tt) {
	case Task::TaskType::TIMED_TASK:
		return STRING_TASKTYPE_TIMED;
		break;
	case Task::TaskType::DEADLINE_TASK:
		return STRING_TASKTYPE_DEADLINE;
		break;
	case Task::TaskType::TASK:
	default:
		return STRING_TASKTYPE_TODO;
		break;
	}
}

string FileWriter::parseBoolToString(bool value) {
	if (value == true) {
		return VALUE_BOOL_TRUE;
	} else {
		return VALUE_BOOL_FALSE;
	}
}

string FileWriter::padNumberWithZero(int number) {
	string numberString = to_string(number);
	if (number < 10) {
		numberString = "0" + numberString;
	}
	return numberString;
}